package com.zhtools.wx.bean;

import com.zhtools.wx.constants.WXPayConstants;
import com.zhtools.wx.exception.WXPayException;
import com.zhtools.wx.utils.WXPayUtil;
import com.zhtools.wx.utils.WXUtil;
import org.apache.commons.lang.StringUtils;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhanghao
 * 统一下单响应结果封装
 */
public class UnityOrderResponse implements Serializable {
    private static final long serialVersionUID = -4026803754741794126L;

    private static final String XML_CONTENT_EMPTY_EXCEPTION = "微信支付统一下单接口响应为空";
    private static final String TRANSFORM_EXCEPTION = "微信支付统一下单接口响应内容转换异常";
    private static final String SIGNATURE_EXCEPTION = "微信支付统一下单接口响应内容签名失败";
    private static final String JSAPI_SIGNATURE_EXCEPTION = "微信支付JSAPI签名失败";

    private String appId;
    private String nonceStr;
    private String paySign;
    private String prepayId;
    private Long timestamp;
    private String packageStr;

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getNonceStr() {
        return nonceStr;
    }

    public void setNonceStr(String nonceStr) {
        this.nonceStr = nonceStr;
    }

    public String getPaySign() {
        return paySign;
    }

    public void setPaySign(String paySign) {
        this.paySign = paySign;
    }

    public String getPrepayId() {
        return prepayId;
    }

    public void setPrepayId(String prepayId) {
        this.prepayId = prepayId;
    }

    public Long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(Long timestamp) {
        this.timestamp = timestamp;
    }

    public String getPackageStr() {
        return packageStr;
    }

    public void setPackageStr(String packageStr) {
        this.packageStr = packageStr;
    }

    /**
     * xml请求报文转成bean
     */
    public static UnityOrderResponse formXmlResponse(String xml, String signKey) throws WXPayException {
        if (StringUtils.isEmpty(xml)) {
            throw new WXPayException(XML_CONTENT_EMPTY_EXCEPTION);
        }
        Map<String, String> map;
        try {
            map = WXPayUtil.xmlToMap(xml);
        } catch (Exception e) {
            throw new WXPayException(TRANSFORM_EXCEPTION, e);
        }
        String return_code = map.get("return_code");
        if ("FAIL".equals(return_code)) {
            String return_msg = map.get("return_msg");
            throw new WXPayException(return_msg);
        }
        boolean checkOK = Boolean.FALSE;
        try {
            checkOK = WXPayUtil.isSignatureValid(xml, signKey);
        } catch (Exception e) {
            throw new WXPayException(SIGNATURE_EXCEPTION, e);
        }
        if (!checkOK) {
            throw new WXPayException(SIGNATURE_EXCEPTION);
        }

        String result_code = map.get("result_code");
        if ("FAIL".equals(result_code)) {
            String err_code = map.get("err_code");
            String err_code_des = map.get("err_code_des");
            String msg = "errorCode:" + err_code + ";errCodeDes:" + err_code_des;
            throw new WXPayException(msg);
        }

        String appId = map.get("appid");
        String prepayId = map.get("prepay_id");
        String packageStr = "prepay_id=" + prepayId;

        UnityOrderResponse response = new UnityOrderResponse();
        response.setAppId(appId);
        response.setTimestamp(WXPayUtil.getCurrentTimestamp());
        response.setNonceStr(WXUtil.generateNonceStr());
        response.setPackageStr(packageStr);
        response.setPrepayId(prepayId);

        Map<String, String> params = new HashMap<>();
        params.put("appId", response.getAppId());
        params.put("timeStamp", response.getTimestamp() + "");
        params.put("nonceStr", response.getNonceStr());
        params.put("package", response.getPackageStr());
        params.put("signType", WXPayConstants.MD5);
        try {
            response.setPaySign(WXPayUtil.generateSignature(params, signKey));
        } catch (Exception e) {
            throw new WXPayException(JSAPI_SIGNATURE_EXCEPTION, e);
        }
        return response;
    }
}
